package com.goods.redis2msyql.util;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;


/**
 * The unit for redis storage.
 * 
 * @author Jianquan Wang
 * 
 */
public class RedisStorage {
	private static Logger logger = LoggerFactory.getLogger(RedisStorage.class);

	private static RedisStorage storage = null;
	private static JedisPool pool = null;
	private static JedisPoolConfig config = null;
	private static int socketTimeout;

	private static String ip;
	private static int port;

	private static String password;

	private static String userName;

	private static int database;

	private RedisStorage() {
	}

	public static synchronized RedisStorage getStorage() {
		if (storage == null) {
			storage = new RedisStorage();
		}
		return storage;
	}

	public synchronized JedisPool getPool() {
		if (pool == null) {
			initConfig();
			logger.info("Connect to redis server with ip:{}  port:{}", ip, port);
			pool = getJedisPool();
		}
		return pool;
	}

	private JedisPool getJedisPool() {

		if (!StringUtils.isBlank(userName)) {

			return new JedisPool(config, ip, port, socketTimeout, password, database, userName);
		} else if (!StringUtils.isBlank(password)) {

			return new JedisPool(config, ip, port, socketTimeout, password, database);
		}

		return new JedisPool(config, ip, port, socketTimeout);
	}

	private static void initConfig() {

		config = new JedisPoolConfig();
		SystemConfigureReader reader = SystemConfigureReader.getReader();

		ip = reader.getProperty("jedis.ip");

		port = Integer.parseInt(reader.getProperty("jedis.port"));

		password = reader.getProperty("jedis.password");

		userName = reader.getProperty("jedis.userName");

		String databaseStr = reader.getProperty("jedis.database");
		if (StringUtils.isBlank(databaseStr)) {
			database = Protocol.DEFAULT_DATABASE;
		} else {
			database = Integer.parseInt(databaseStr);
		}

		String blockWhenExhaustedStr = reader.getProperty("jedis.pool.blockWhenExhausted");
		if ("true".equals(blockWhenExhaustedStr)) {
			config.setBlockWhenExhausted(true);
		} else if ("false".equals(blockWhenExhaustedStr)) {
			config.setBlockWhenExhausted(false);
		}

		String evictionPolicyClassName = reader.getProperty("jedis.pool.evictionPolicyClassName");
		if (StringUtils.isNotEmpty(evictionPolicyClassName)) {
			config.setEvictionPolicyClassName(evictionPolicyClassName);
		}

		String jmxEnabled = reader.getProperty("jedis.pool.jmxEnabled");
		if ("true".equals(jmxEnabled)) {
			config.setJmxEnabled(true);
		} else if ("false".equals(jmxEnabled)) {
			config.setJmxEnabled(false);
		}

		String jmxNamePrefix = reader.getProperty("jedis.pool.jmxNamePrefix");
		if (StringUtils.isNotEmpty(jmxNamePrefix)) {
			config.setJmxNamePrefix(jmxNamePrefix);
		}

		String lifo = reader.getProperty("jedis.pool.lifo");
		if ("true".equals(lifo)) {
			config.setLifo(true);
		} else if ("false".equals(lifo)) {
			config.setLifo(false);
		}

		String maxIdle = reader.getProperty("jedis.pool.maxIdle");
		if (StringUtils.isNotEmpty(maxIdle)) {
			config.setMaxIdle(Integer.parseInt(maxIdle));
		}

		String maxTotal = reader.getProperty("jedis.pool.maxTotal");
		if (StringUtils.isNotEmpty(maxTotal)) {
			config.setMaxTotal(Integer.parseInt(maxTotal));
		}

		String maxWaitMillis = reader.getProperty("jedis.pool.maxWaitMillis");
		if (StringUtils.isNotEmpty(maxWaitMillis)) {
			config.setMaxWaitMillis(Long.parseLong(maxWaitMillis));
		}

		String minEvictableIdleTimeMillis = reader.getProperty("jedis.pool.minEvictableIdleTimeMillis");
		if (StringUtils.isNotEmpty(minEvictableIdleTimeMillis)) {
			config.setMinEvictableIdleTimeMillis(Long.parseLong(minEvictableIdleTimeMillis));
		}

		String minIdle = reader.getProperty("jedis.pool.minIdle");
		if (StringUtils.isNotEmpty(minIdle)) {
			config.setMinIdle(Integer.parseInt(minIdle));
		}

		String numTestsPerEvictionRun = reader.getProperty("jedis.pool.numTestsPerEvictionRun");
		if (StringUtils.isNotEmpty(numTestsPerEvictionRun)) {
			config.setNumTestsPerEvictionRun(Integer.parseInt(numTestsPerEvictionRun));
		}

		String softMinEvictableIdleTimeMillis = reader.getProperty("jedis.pool.softMinEvictableIdleTimeMillis");
		if (StringUtils.isNotEmpty(softMinEvictableIdleTimeMillis)) {
			config.setSoftMinEvictableIdleTimeMillis(Long.parseLong(softMinEvictableIdleTimeMillis));
		}

		String testOnBorrow = reader.getProperty("jedis.pool.testOnBorrow");
		if ("true".equals(testOnBorrow)) {
			config.setTestOnBorrow(true);
		} else if ("false".equals(testOnBorrow)) {
			config.setTestOnBorrow(false);
		}

		String testOnReturn = reader.getProperty("jedis.pool.testOnReturn");
		if ("true".equals(testOnReturn)) {
			config.setTestOnReturn(true);
		} else if ("false".equals(testOnReturn)) {
			config.setTestOnReturn(false);
		}

		String testWhileIdle = reader.getProperty("jedis.pool.testWhileIdle");
		if ("true".equals(testWhileIdle)) {
			config.setTestWhileIdle(true);
		} else if ("false".equals(testWhileIdle)) {
			config.setTestWhileIdle(false);
		}

		String timeBetweenEvictionRunsMillis = reader.getProperty("jedis.pool.timeBetweenEvictionRunsMillis");
		if (StringUtils.isNotEmpty(timeBetweenEvictionRunsMillis)) {
			config.setTimeBetweenEvictionRunsMillis(Long.parseLong(timeBetweenEvictionRunsMillis));
		}

		String socketTimeoutStr = reader.getProperty("jedis.pool.socketTimeout");
		if (StringUtils.isNoneEmpty(socketTimeoutStr)) {
			socketTimeout = Integer.parseInt(socketTimeoutStr);
		}

		logger.info("Inited the configuration for redis server.");
	}
}
